﻿using System;
using System.Linq.Expressions;
using System.Collections.Generic;
using QbservableCore.Serialization.Helpers;
using System.Runtime.Serialization;

namespace QbservableCore.Serialization
{
    [DataContract]
    public class UnaryNode : ExpRepresentationBase
    {
        [DataMember]
        public ExpRepresentationBase Operand { get; set; }

        private int OperatorValue { get; set; }

        [DataMember]
        public LightweightSerializableType TypeToConvertTo { get; set; }

        [DataMember]
        public ExpressionType Operator
        {
            get
            {
                return (ExpressionType)OperatorValue;
            }
            set
            {
                OperatorValue = (int)value;
            }
        }

        protected internal override Expression ToExpression(ExepressionBuilderCache exepressionBuilderCache)
        {
            Type type = TypeToConvertTo != null ? TypeToConvertTo.ToType() : null;
            return Expression.MakeUnary(Operator, Operand.ToExpression(exepressionBuilderCache), type);
        }

        protected override void TraverseChildren(Func<ExpRepresentationBase, ExpRepresentationBase> action)
        {
            Operand = Operand.Traverse(action);
        }

        public override string ToString()
        {
            if (Operator == ExpressionType.TypeAs)
            {
                return string.Format("({0})", Operand);
            }
            string opr = GetOperator(Operator);
            string operand = Operand is ConstantNode || opr == string.Empty ? Operand.ToString() : "(" + Operand + ")";
            return opr + operand;
        }

        private string GetOperator(ExpressionType opr)
        {
            switch (opr)
            {
                case ExpressionType.Convert:
                    throw new NotImplementedException();  //TODO
                    //return "(" + Type.Name + ")";
                case ExpressionType.Negate:
                    return "-";
                case ExpressionType.Not:
                    return "!";
                case ExpressionType.Quote:
                    return string.Empty;
                default:
                    return "<???>";
            }
        }
    }
}